package sg.edu.nus.iss.awsdynamodb;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodb.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.services.dynamodb.model.ComparisonOperator;
import com.amazonaws.services.dynamodb.model.Condition;
import com.amazonaws.services.dynamodb.model.DeleteItemRequest;
import com.amazonaws.services.dynamodb.model.DeleteItemResult;
import com.amazonaws.services.dynamodb.model.Key;
import com.amazonaws.services.dynamodb.model.PutItemRequest;
import com.amazonaws.services.dynamodb.model.PutItemResult;
import com.amazonaws.services.dynamodb.model.QueryRequest;
import com.amazonaws.services.dynamodb.model.QueryResult;
import com.amazonaws.services.dynamodb.model.ScanRequest;
import com.amazonaws.services.dynamodb.model.ScanResult;

import sg.edu.nus.iss.CONFIG;
import sg.edu.nus.iss.stockex.*;
import sg.edu.nus.iss.Util;
public class StockQuoteTable implements DynamoDBTableInf<StockQuote> {
	
	private AmazonDynamoDBClient dynamoDB = DynamoDB.client();
	@Override
	
	public Map<String, AttributeValue> newItem(StockQuote quote) {
		Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
		item.put("code", new AttributeValue(quote.getCode()));
		item.put("high", new AttributeValue().withN(Double.toString(quote.getHighPrice())));
		item.put("low", new AttributeValue().withN(Double.toString(quote.getLowPrice())));
		item.put("open", new AttributeValue().withN(Double.toString(quote.getOpenPrice())));
		item.put("close", new AttributeValue().withN(Double.toString(quote.getClosePrice())));
		item.put("volume", new AttributeValue().withN(Double.toString(quote.getVolume())));
		item.put("name", new AttributeValue(quote.getName()));
		item.put("date", new AttributeValue(Util.formatDate(quote.getTradeDate())));
		return item;
	}

	@Override
	public boolean Add(StockQuote item) {
		 boolean status = false;
		 try{
		 Map<String,AttributeValue> map = newItem(item);
		 PutItemRequest putItemRequest = new PutItemRequest(CONFIG.STOCK_QUOTE_TABLE_NAME, map);
		 PutItemResult putItemResult = dynamoDB.putItem(putItemRequest);
		 System.out.println("Result: " + putItemResult);
		 if(putItemResult!=null)
		 {
			 status =  true;
		 }
		 }catch (Exception e) {
			 e.printStackTrace();
			// TODO: handle exception
		}
		
		 return status;
	}

	@Override
	public boolean Delete(StockQuote item) {
		
		boolean status = false;
		try{
			DeleteItemRequest deleteItemRequest = new DeleteItemRequest().withTableName(CONFIG.STOCK_QUOTE_TABLE_NAME).withKey(new Key().withHashKeyElement(new AttributeValue(item.getCode())));
			DeleteItemResult result = dynamoDB.deleteItem(deleteItemRequest);
			if(result!=null)
			{
				status = true;	
			}
		}catch (Exception e) {
			// TODO: handle exception
		}
		return status;
		
	}
	
	//past 30 days based on code and date..
	public List<StockQuote> query(String code, String date)
	{
		List<StockQuote> stockList = new ArrayList<StockQuote>();
		String backDate = Util.oneMonthBackDate(date);
		
		stockList =  query(code, date, backDate);
		
		return stockList;
	}
	
	public List<StockQuote> query(String code, String startDate, String endDate)
	{
		System.out.println("######################");
		System.out.println("code = " + code);
		System.out.println("startDate = " + startDate);
		System.out.println("endDate = " + endDate);
		List<StockQuote> stockList = new ArrayList<StockQuote>();
		
		Condition rangeKeyCondition = new Condition()
		.withComparisonOperator(ComparisonOperator.BETWEEN.toString())
		.withAttributeValueList(new AttributeValue().withS(startDate), new AttributeValue().withS(endDate));
		
		QueryRequest queryRequest = new QueryRequest().withTableName(CONFIG.STOCK_QUOTE_TABLE_NAME)
				.withHashKeyValue(new AttributeValue().withS(code))
				.withRangeKeyCondition(rangeKeyCondition);
		QueryResult result = dynamoDB.query(queryRequest);
		for (Map<String, AttributeValue> item : result.getItems()) {
			stockList.add(convertMapToQuote(item));
		}
		return stockList;
	}
	
	public ArrayList<StockQuote> listItems()
	{
		DynamoDB.waitForTableToBecomeAvailable(CONFIG.STOCK_QUOTE_TABLE_NAME);
    	ArrayList<StockQuote> quoteList = new ArrayList<StockQuote>();
        HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
        Condition condition = new Condition()
            .withComparisonOperator(ComparisonOperator.GT.toString())
            .withAttributeValueList(new AttributeValue("2012-02-10"));
        scanFilter.put("date", condition);
        ScanRequest scanRequest = new ScanRequest(CONFIG.STOCK_QUOTE_TABLE_NAME).withScanFilter(scanFilter);
        ScanResult scanResult = dynamoDB.scan(scanRequest);
        List<Map<String,AttributeValue>> quoteMapList  = scanResult.getItems();
        System.out.println("quoteMapList:"+quoteMapList.size());
        String code = "";
        StockQuote quote = null;
        AttributeValue attr = new AttributeValue();
        System.out.println("Dispalying all the data....");
        for (Map<String, AttributeValue> map : quoteMapList) {
        	quote = convertMapToQuote(map);
        
        	if(quote!=null)
        	{
        		quoteList.add(quote);
        	}
		}
        return quoteList;
	}

	 public StockQuote convertMapToQuote(Map<String, AttributeValue> map)
	    {
	    	StockQuote quote = null;
	    	try {
	    		 
	    	 String code = map.get("code").getS();
	    	 System.out.println(code);
	    	 String tradeDate = map.get("date").getS();
	    	 Date date = Util.parseDate(tradeDate);
	    	 String name = map.get("name").getS();
	    	 double highPrice = new Double(map.get("high").getN()).doubleValue();
	    	 double lowPrice = new Double(map.get("low").getN()).doubleValue();
	    	 double openPrice = new Double(map.get("open").getN()).doubleValue();
	    	 double closePrice = new Double(map.get("close").getN()).doubleValue();
	    	 double volume =  new Double(map.get("high").getN()).doubleValue();
	    	 long vol = (long)volume;
	    	 quote = new StockQuote(code,date,name,highPrice,lowPrice,openPrice,closePrice,vol);
			} catch (Exception e) {
				System.out.println(e.getMessage());
				e.printStackTrace();
				return null;
				// TODO: handle exception
			}
	    	return quote;
	    }
	    
	
	public  void createTable() {
		DynamoDB.createTable(CONFIG.STOCK_QUOTE_TABLE_NAME, CONFIG.STOCK_QUOTE_PRIMARY_KEY, CONFIG.STOCK_QUOTE_PRIMARY_KEY_TYPE,CONFIG.STOCK_QUOTE_RANGE_KEY,CONFIG.STOCK_QUOTE_RANGE_KEY_TYPE);
	}

}
